package com.sztx.pay.center.rpc.component;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.mortbay.log.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.sztx.pay.center.common.util.ConfigUtil;
import com.sztx.pay.center.common.util.Constance;
import com.sztx.pay.center.common.util.Constance.BindCardStatus;
import com.sztx.pay.center.common.util.Constance.BindCardType;
import com.sztx.pay.center.common.util.Constance.CallBackOrderState;
import com.sztx.pay.center.common.util.Constance.CardActType;
import com.sztx.pay.center.common.util.Constance.CardType;
import com.sztx.pay.center.common.util.Constance.ChargeOrderState;
import com.sztx.pay.center.common.util.Constance.IdCardType;
import com.sztx.pay.center.common.util.Constance.PayFlowState;
import com.sztx.pay.center.common.util.Constance.TradeMessageType;
import com.sztx.pay.center.common.util.Constance.TradeOrderType;
import com.sztx.pay.center.common.util.Constance.UserActType;
import com.sztx.pay.center.common.util.IDCardUtil;
import com.sztx.pay.center.common.util.JFUtils;
import com.sztx.pay.center.common.util.ValidateUtil;
import com.sztx.pay.center.common.yhbf.YHBFSensitiveEnc;
import com.sztx.pay.center.core.service.AccountService;
import com.sztx.pay.center.core.service.ActService;
import com.sztx.pay.center.core.service.BillnoService;
import com.sztx.pay.center.core.service.CallBackService;
import com.sztx.pay.center.core.service.MqMessageService;
import com.sztx.pay.center.core.service.OrderMappingService;
import com.sztx.pay.center.core.service.PayCoreCallBack;
import com.sztx.pay.center.core.service.PayCoreService;
import com.sztx.pay.center.core.service.RiskControlService;
import com.sztx.pay.center.core.service.SettleService;
import com.sztx.pay.center.core.service.UserInfoService;
import com.sztx.pay.center.core.service.bean.CallBackInfo;
import com.sztx.pay.center.core.service.bean.PayCoreAccountInfo;
import com.sztx.pay.center.core.service.bean.PayCoreResult;
import com.sztx.pay.center.core.service.bean.PayCoreTradeInfo;
import com.sztx.pay.center.core.service.bean.TradeInfo;
import com.sztx.pay.center.core.service.util.SettleTradeType;
import com.sztx.pay.center.core.service.util.SettleType;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderRechargeMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.UserBindCardMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.redis.LockRedisDAO;
import com.sztx.pay.center.dataaccess.domain.OrderRechargeDO;
import com.sztx.pay.center.dataaccess.domain.UserActDO;
import com.sztx.pay.center.dataaccess.domain.UserBindCardDO;
import com.sztx.pay.center.rpc.api.domain.ChargeRequest;
import com.sztx.pay.center.rpc.api.domain.TradeBaseRequest;
import com.sztx.pay.center.rpc.api.domain.TradeFlowMessage;
import com.sztx.pay.center.rpc.api.domain.TradeResponse;
import com.sztx.pay.risk.rpc.api.domain.TradeType;
import com.sztx.se.common.exception.BusinessException;
import com.sztx.se.common.util.StringUtil;
import com.sztx.se.rpc.dubbo.client.DubboClientFactory;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.BankUtilRpcService;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.ReqGetBankCardInfo;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.RespGetBankCardInfo;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.RespGetBankCardInfo.BankCardInfo;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.RespBindBankCard;

/**
 * 用户余额充值，暂只提供快捷支付方式 操作步骤： a. 用户@银行 -> 通行@第三方支付 (快捷支付) b1. 通行现金@通付 -> 用户@通付
 * (批量转账) b2. 通行现金@通付 -> 通行收益@通付 (批量转账) 流程处理： 当a流程成功则为成功，如果b流程有出现异常则通过补单处理
 * 
 * @author xiaosc
 * @version [版本号, 2016年6月21日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class TradeChargeService extends TradeService implements PayCoreCallBack {

	BillnoService billnoService;
	PayCoreService payCoreService;
	SettleService settleService;
	RiskControlService riskControlService;

	private long calculateHandlingFee;// 手续费

	private long payAmount;// 实际充值金额

	OrderRechargeMysqlDAO orderRechargeMysqlDAO;
	@Autowired
	UserBindCardMysqlDAO userBindCardMysqlDAO;

	AccountService accountService;

	@Autowired
	OrderMappingService orderMappingService;

	@Autowired
	CallBackService callBackService;

	@Autowired
	private LockRedisDAO lockRedisDAO;
	
	@Autowired
	private DubboClientFactory dubboConsumerFactory;
	@Autowired
	private ActService actService;
	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private MqMessageService mqMessageService;
	public OrderRechargeMysqlDAO getOrderRechargeMysqlDAO() {
		return orderRechargeMysqlDAO;
	}

	public void setOrderRechargeMysqlDAO(OrderRechargeMysqlDAO orderRechargeMysqlDAO) {
		this.orderRechargeMysqlDAO = orderRechargeMysqlDAO;
	}

	public AccountService getAccountService() {
		return accountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public BillnoService getBillnoService() {
		return billnoService;
	}

	public void setBillnoService(BillnoService billnoService) {
		this.billnoService = billnoService;
	}

	public PayCoreService getPayCoreService() {
		return payCoreService;
	}

	public void setPayCoreService(PayCoreService payCoreService) {
		this.payCoreService = payCoreService;
	}

	public SettleService getSettleService() {
		return settleService;
	}

	public void setSettleService(SettleService settleService) {
		this.settleService = settleService;
	}

	public RiskControlService getRiskControlService() {
		return riskControlService;
	}

	public void setRiskControlService(RiskControlService riskControlService) {
		this.riskControlService = riskControlService;
	}

	@Override
	void checkPrivateParam(Map<String, String> params) {
		String userId = params.get("payerUserId");
		String bindNo = params.get("bindNo");
		String bankId = params.get("bankId");
		String amount = params.get("amount");
		String channelId = params.get("channelId");
		String businessType = params.get("businessType");

		String bindType = params.get("bindType");
		String cardActType = params.get("cardActType");
		String cardType = params.get("cardType");
		String realName = params.get("realName");
		String identityNo = params.get("identityNo");
		String mobileNo = params.get("mobileNo");
		String cardNo = params.get("cardNo");
		String returnUrl = params.get("returnUrl");
		String notifyUrl = params.get("notifyUrl");

		String cvv = params.get("cvv");
		String expireDate = params.get("expireDate");
		String cardProvince = params.get("cardProvince");
		String cardCity = params.get("cardCity");
		String bankAddr = params.get("bankAddr");
		boolean isBindCard = Boolean.valueOf(params.get("bindCardFlag"));

		ValidateUtil.isNotBlank(channelId, "channelId不能为空");
		ValidateUtil.isNotBlank(businessType, "businessType不能为空");
		ValidateUtil.isNotBlank(userId, "userId不能为空");

		ValidateUtil.isNotBlank(amount, "amount不能为空");
		ValidateUtil.isNotBlank(notifyUrl, "notifyUrl不能为空");

		if (StringUtil.isNotBlank(bindNo)) {
			ValidateUtil.strEqualLen(bindNo, 8, "bindNo格式不正确");
		}
		if (StringUtil.isNotBlank(bankId)) {
			ValidateUtil.strEqualLen(bankId, 7, "bankId格式不正确");
		}
		if (StringUtil.isBlank(bindNo) && StringUtil.isBlank(bankId)) {
			throw new BusinessException("bindNo、bankId不能都为空");
		}
		
		if (StringUtil.isBlank(bindNo) && bankId.startsWith("1")) {
			ValidateUtil.isNotBlank(returnUrl, "网银支付,returnUrl不能为空");
		}
		if (isBindCard) {
			ValidateUtil.isNotBlank(bankId, "充值并绑卡bankId不能为空");
			ValidateUtil.isNotBlank(realName, "realName不能为空");
			ValidateUtil.isNotBlank(identityNo, "identityNo不能为空");// 绑定快捷支付卡时不能为空
			ValidateUtil.isNotBlank(mobileNo, "mobileNo不能为空"); // 绑定快捷支付卡时不能为空
			ValidateUtil.isNotBlank(bindType, "bindType不能为空");
			ValidateUtil.notNull(cardActType, "cardActType不能为空");
			ValidateUtil.notNull(cardType, "cardType不能为空");

			ValidateUtil.isBetween(cardNo.length(), 16, 64, "cardNo参数传入有误");
			ValidateUtil.isTrue(IDCardUtil.isIDCard(identityNo), "identityNo参数传入有误");
			ValidateUtil.isMobile(mobileNo, "mobileNo传入有误");

			if (cardType.equals("2")) {
				if (!JFUtils.isJFChannel(channelId)) {
					throw new BusinessException("当前渠道不允许绑定信用卡!");
				}
				ValidateUtil.isNotBlank(cvv, "cvv不能为空");
				ValidateUtil.isNotBlank(expireDate, "expireDate不能为空");
			}
			if(cardActType.equals("2")){
				ValidateUtil.isNotBlank(cardProvince, "cardProvince不能为空");
				ValidateUtil.isNotBlank(cardCity, "cardCity不能为空");
				ValidateUtil.isNotBlank(bankAddr, "bankAddr不能为空");
			}
		}

	}

	@Override
	boolean isRepeatOrder(Map<String, String> params) {
		String orderId = params.get("orderId");

		OrderRechargeDO orderRechargeDO = orderRechargeMysqlDAO.findByOrderId(orderId);
		if (orderRechargeDO != null) {
			return true;
		}

		return false;
	}

	@Override
	String recordOrder(TradeBaseRequest request) {

		if (!(request instanceof ChargeRequest)) {
			logger.error("请求参数错误request不是ChargeRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}
		ChargeRequest chargeRequest = (ChargeRequest) request;

		int amount = chargeRequest.getAmount();
		String attach = chargeRequest.getAttach();
		String bindNo = chargeRequest.getBindNo();
		String bankId = chargeRequest.getBankId();
		String expireTime = chargeRequest.getExpireTime();
		String notifyUrl = chargeRequest.getNotifyUrl();
		String orderId = chargeRequest.getOrderId();
		String orderTime = chargeRequest.getOrderTime();
		String returnUrl = chargeRequest.getReturnUrl();
		String sign = chargeRequest.getSign();
		String signType = chargeRequest.getSignType();
		String userId = chargeRequest.getPayerUserId();
		String srcIp = chargeRequest.getSrcIp();
		String srcChannel = chargeRequest.getSrcChannel();
		String platChannelId = chargeRequest.getChannelId();
		String businessType = chargeRequest.getBusinessType();
		Boolean bindCardFlag = chargeRequest.getBindCardFlag();
		Integer cardType = chargeRequest.getCardType();
		//网银,支付宝扫码,威富通扫码直接返回
		if (StringUtil.isEmpty(bindNo) && !bankId.startsWith("0") && !bankId.startsWith("2")) {
			OrderRechargeDO lastOrder = orderRechargeMysqlDAO.findOrderByPayParams(orderId, amount, userId, bankId);
			if (lastOrder != null) return lastOrder.getRechargeOrderId();
		}
		
		// 生成充值订单号
		String reChargeNo = billnoService.nextChargeNo();
		byte payType = new Byte("1");
		if (StringUtil.isNotBlank(bankId)) {
			String startWith = bankId.substring(0, 1);
			if (startWith.equals("1")) {
				payType = new Byte("0");
			} else if (startWith.equals("2")) {
				payType = new Byte("1");
			} else if (startWith.equals("3")) {
				payType = new Byte("2");
			}
		}

		// 支付银行卡信息
		bankId = StringUtil.isBlank(bankId) ? payerBindCardInfo.getBankId() : bankId;
		
		// 查询手续费
		CardType RCardType = null;
		if(bindCardFlag != null && bindCardFlag){
			RCardType = CardType.valueOf(cardType);
		}else if(payerBindCardInfo != null && payerBindCardInfo.getCardType() != null){
			RCardType = CardType.valueOf(payerBindCardInfo.getCardType());
		}
		
		Log.info("-------calculateHandlingFee-------cardType:"+cardType);
		long calculateHandlingFee = settleService.calculateHandlingFee(SettleTradeType.CHARGE, SettleType.NOW, userId, (long)amount,platChannelId,bankId,RCardType);
		this.calculateHandlingFee = calculateHandlingFee;

		if (amount <= calculateHandlingFee) {
			throw new BusinessException("手续费不能大于、等于交易金额");
		}

		long payAmount = (long) amount - calculateHandlingFee;
		this.payAmount = payAmount;

		// 进行绑卡支付先进行卡信息记录
		bindNo = recordCardInfo(chargeRequest);

		OrderRechargeDO orderRechargeDO = new OrderRechargeDO();
		orderRechargeDO.setPayerUserAct(payerActInfo.getActNo());
		orderRechargeDO.setAddTime(new Date());
		orderRechargeDO.setPayBankId(bankId);
		orderRechargeDO.setInnerStatus(1);
		orderRechargeDO.setNotifyUrl(notifyUrl);
		orderRechargeDO.setOrderId(orderId);
		orderRechargeDO.setPayAmount(payAmount);
		orderRechargeDO.setPayTime(null);
		orderRechargeDO.setPayType(payType);
		orderRechargeDO.setRechargeAmount((long) amount);
		orderRechargeDO.setRechargeChannel(new Byte(srcChannel));
		orderRechargeDO.setRechargeFee(calculateHandlingFee);
		orderRechargeDO.setRechargeOrderId(reChargeNo);
		orderRechargeDO.setPayerBindNo(bindNo);
		orderRechargeDO.setOrderStatus((byte) Constance.ChargeOrderState.CHARGE_STATUS_INIT.getCode());
		orderRechargeDO.setOrderDesc(Constance.ChargeOrderState.CHARGE_STATUS_INIT.getDesc());
		orderRechargeDO.setRemark(attach);
		orderRechargeDO.setReturnUrl(returnUrl);
		orderRechargeDO.setSourceIp(srcIp);
		orderRechargeDO.setPayerUserId(userId);

		orderRechargeDO.setPlatChannelId(platChannelId);
		orderRechargeDO.setBusinessType(businessType);
		if (bindCardFlag != null && bindCardFlag) {
			orderRechargeDO.setIsBindCard(1);
		}

		orderRechargeMysqlDAO.save(orderRechargeDO);
		return reChargeNo;
	}

	@Override
	UserBindCardDO getPayerBindInfo(Map<String, String> params) {
		String bindNo = params.get("bindNo");
		String userId = params.get("payerUserId");
		String channelId = params.get("channelId");

		UserBindCardDO userBindCardDO = accountService.findUserBindInfo(bindNo, userId, BindCardType.BIND_QUICK_PAY);
		
		if (userBindCardDO == null ) throw new BusinessException("未查询到绑定号【"+ bindNo +"】相关信息" );
		
		if(userBindCardDO.getCardType() == Constance.CardType.CARD_CREDIT.getValue() && !JFUtils.isJFChannel(channelId)) {
			throw new BusinessException("暂不支持使用信用卡支付");
		}
		
		return userBindCardDO;
	}

	@Override
	UserActDO getPayerActInfo(TradeBaseRequest request) {
		if (!(request instanceof ChargeRequest)) {
			logger.error("请求参数错误request不是ChargeRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}
		ChargeRequest chargeRequest = (ChargeRequest) request;

		String userId = chargeRequest.getPayerUserId();
		String channelId = chargeRequest.getChannelId();
		//查询用户详情
		UserActType userActType = UserActType.CASH;
		if (JFUtils.isJFChannel(channelId)) {
			userActType = UserActType.JF;
		}

		return actService.findValidActInfo(userId, userActType, false);
	}

	@Override
	UserActDO getPayeeActInfo(TradeBaseRequest request) {
		return null;
	}

	@Override
	UserBindCardDO getPayeeBindInfo(Map<String, String> params) {
		return null;
	}

	@Override
	TradeResponse invokePayCore(Map<String, String> params) {
		logger.info("开始调用invokePayCore");
		String notifyUrl = params.get("notifyUrl");
		String rechargeOrderId = params.get("tradeOrderId");
		String remark = params.get("remark");
		String amount = params.get("amount");
		String bankId = params.get("bankId");
		String businessType = params.get("businessType");
		String returnUrl = params.get("returnUrl");
		String openId = params.get("openId");
		String authCode = params.get("authCode");
		String gateWayChannelId = params.get("gateWayChannelId");
		String routeNo = params.get("routeNo");
		
		bankId = StringUtil.isBlank(bankId) ? payerBindCardInfo.getBankId() : bankId;
		
		if (!StringUtil.isBlank(returnUrl)) {
			returnUrl = ConfigUtil.innerReturnUrl;// 将回调地址转换
		}
		
		OrderRechargeDO findById = orderRechargeMysqlDAO.findById(rechargeOrderId);
		if (findById.getOrderStatus() == Constance.B2COrderState.PAYING.getCode()) {
			String payParams = findById.getPayParams();
			PayCoreResult result = JSONObject.parseObject(payParams, PayCoreResult.class);
			
			TradeResponse resonse = new TradeResponse();
			resonse.setPayUrl(result.getPayUrl());
			resonse.setTradeOrderId(rechargeOrderId);
			resonse.setResultCode(String.valueOf(PayFlowState.PAYING));
			resonse.setResultMsg(result.getTradeDesc());
			resonse.setPayParams(result.getPayParams());

			return resonse;
		}
		// 生成支付映射订单
		String payMappingOrderId = orderMappingService.addMappingOrder(rechargeOrderId, (byte) Constance.PayFlowType.PAY.getCode());

		TradeInfo tradeInfo = new TradeInfo();
		tradeInfo.setAmount(new Integer(amount));
		tradeInfo.setGoodsDetail("用户充值余额");
		tradeInfo.setGoodsName("用户充值余额");
		tradeInfo.setNotifyUrl(notifyUrl);
		// tradeInfo.setReferOrderId(payMappingOrderId);
		// tradeInfo.setReferOrderType(Constance.TradeOrderType.CHARGE_ORDER.getCode());
		tradeInfo.setRemark("用户充值余额");
		tradeInfo.setReturnUrl(returnUrl);
		tradeInfo.setBankId(bankId);
		tradeInfo.setOrderType(TradeOrderType.CHARGE_ORDER);
		tradeInfo.setOriginOrderNo(rechargeOrderId);
		// 此处传入映射订单号
		tradeInfo.setTradeOrderId(payMappingOrderId);
		tradeInfo.setFeeAmount(calculateHandlingFee);
		tradeInfo.setBusinessType(businessType);
		tradeInfo.setAuthCode(authCode);
		tradeInfo.setGateWayChannelId(gateWayChannelId);
		
		PayCoreAccountInfo payerAccount = new PayCoreAccountInfo();

		payerAccount.setPayerUserId(payerActInfo.getUserId());
		payerAccount.setPayerUserType(payerActInfo.getUserType());
		payerAccount.setPayerActType(UserActType.valueOf(payerActInfo.getActType()));
		payerAccount.setPayerActNo(payerActInfo.getActNo());
		// payerAccount.setActNo(payerActInfo.getActNo());
		payerAccount.setOpenId(openId);

		if (payerBindCardInfo != null) {
			payerAccount.setBankAct(payerBindCardInfo.getCardNo());
			payerAccount.setBankId(payerBindCardInfo.getBankId());
			// if(payerBindCardInfo.getChannelBindCardNo() != null){
			// payerAccount.setMobile(payerBindCardInfo.getMobileNo());
			// }else{
			payerAccount.setCardType(CardType.valueOf(payerBindCardInfo.getCardType()));
			payerAccount.setIdentityType(IdCardType.valueOf(payerBindCardInfo.getIdentityType()));
			payerAccount.setIdentityNo(payerBindCardInfo.getIdentityNo());
			payerAccount.setMobile(payerBindCardInfo.getMobileNo());
			payerAccount.setRealName(payerBindCardInfo.getRealName());
			payerAccount.setBankName(payerBindCardInfo.getBankName());
			payerAccount.setCardActType(CardActType.valueOf(payerBindCardInfo.getCardActType()));
			// }

			if (CardType.CARD_CREDIT.getValue() == payerBindCardInfo.getCardType()) {
				payerAccount.setBankActCvv(payerBindCardInfo.getCardCvv());
				payerAccount.setBankActExpire(payerBindCardInfo.getExpireDate());
			}
		}

		if(JFUtils.isJFChannel(findById.getPlatChannelId()) && StringUtil.isBlank(routeNo)){
			String jfRouteNo = JFUtils.getJfDefaultRouteNo(1);
			tradeInfo.setRouteNo(jfRouteNo);
		}else if(StringUtil.isNotBlank(routeNo)){
			tradeInfo.setRouteNo(routeNo);
		}
		
		PayCoreResult chargeResult = payCoreService.pay(payerAccount, tradeInfo, "tradeChargeService");
		logger.info("充值第一步同步状态:" + chargeResult.getTradeSataus());
		int chargeSataus = chargeResult.getTradeSataus();
		ChargeOrderState orderStatus = null;
		if (chargeSataus == Constance.PayFlowState.PAYING.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_IN;
		if (chargeSataus == Constance.PayFlowState.SUCCESS.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_SUCCESS;
		if (chargeSataus == Constance.PayFlowState.FAIL.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_FAIL;
		if (chargeSataus == Constance.PayFlowState.EXCEPTION.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_EXCEPTION;

		callBack(rechargeOrderId, orderStatus.getCode(), remark);

		OrderRechargeDO orderRechargeDO = new OrderRechargeDO();
		orderRechargeDO.setRechargeOrderId(rechargeOrderId);
		orderRechargeDO.setOrderStatus((byte) orderStatus.getCode());
		orderRechargeDO.setOrderDesc(orderStatus.getDesc());
		orderRechargeDO.setPayChannelId(chargeResult.getChannelId());
		orderRechargeDO.setPayParams(JSONObject.toJSONString(chargeResult));
		orderRechargeMysqlDAO.update(orderRechargeDO);

		TradeResponse response = new TradeResponse();
		response.setResultCode(String.valueOf(chargeSataus));
		response.setTradeOrderId(rechargeOrderId);
		response.setResultMsg(chargeResult.getTradeDesc());
		response.setPayUrl(chargeResult.getPayUrl());
		response.setPayParams(chargeResult.getPayParams());
		response.setCodeImgUrl(chargeResult.getCodeImgUrl());
		
		return response;
	}

	@Override
	void handerPayCoreResult() {

	}

	public long getCalculateHandlingFee() {
		return calculateHandlingFee;
	}

	public void setCalculateHandlingFee(long calculateHandlingFee) {
		this.calculateHandlingFee = calculateHandlingFee;
	}

	public long getPayAmount() {
		return payAmount;
	}

	public void setPayAmount(long payAmount) {
		this.payAmount = payAmount;
	}

	@Override
	public void callPayResult(PayCoreTradeInfo tradeInfo) {

		String mappingOrderId = tradeInfo.getReferOrderId();
		PayFlowState payFlowState = tradeInfo.getPayFlowState();
		String userId = tradeInfo.getPayerUserId();

		ChargeRequest chargeRequest = new ChargeRequest();
		chargeRequest.setPayerUserId(userId);

		logger.info("充值回调:" + tradeInfo);

		String referOrderId = orderMappingService.getTradeOrderId(mappingOrderId);

		OrderRechargeDO orderRechargeDO = orderRechargeMysqlDAO.findById(referOrderId);
		ChargeOrderState orderStatus = ChargeOrderState.valueOf(orderRechargeDO.getOrderStatus());
		int tradeStatus = payFlowState.getCode();
		
		if (tradeStatus == Constance.PayFlowState.PAYING.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_IN;
		if (tradeStatus == Constance.PayFlowState.SUCCESS.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_SUCCESS;
		if (tradeStatus == Constance.PayFlowState.FAIL.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_FAIL;
		if (tradeStatus == Constance.PayFlowState.EXCEPTION.getCode())
			orderStatus = Constance.ChargeOrderState.CHARGE_STATUS_EXCEPTION;

		
		if (orderStatus.equals(Constance.ChargeOrderState.CHARGE_STATUS_SUCCESS)) {
			int isBindCard = orderRechargeDO.getIsBindCard();
			if (isBindCard == 1) {
				String bindCardNo = orderRechargeDO.getPayerBindNo();
				UserBindCardDO updateBindCard = new UserBindCardDO();
				updateBindCard.setStatus(BindCardStatus.BIND.getValue());
				userBindCardMysqlDAO.updateBindCard(updateBindCard, bindCardNo);
			}
		}
		
		callBack(referOrderId, orderStatus.getCode(), orderRechargeDO.getRemark());
		
		OrderRechargeDO updateOrderRechargeDO = new OrderRechargeDO();
		updateOrderRechargeDO.setRechargeOrderId(referOrderId);
		updateOrderRechargeDO.setOrderStatus((byte) orderStatus.getCode());
		updateOrderRechargeDO.setOrderDesc(orderStatus.getDesc());
		updateOrderRechargeDO.setPayChannelId(tradeInfo.getChannelId());
		orderRechargeMysqlDAO.update(updateOrderRechargeDO);

	}

	
	@Async
	private void callBack(String chargeOrderId, int state, String attach) {
		logger.info("充值调用callBack:" + chargeOrderId + "," + state);
		Date payTime = new Date();
		OrderRechargeDO orderRechargeDO = orderRechargeMysqlDAO.findById(chargeOrderId);
		// 通知业务系统
		ChargeOrderState transferOrderState = ChargeOrderState.valueOf(state);
		CallBackOrderState callBackOrderState = null;
		if (transferOrderState.equals(ChargeOrderState.CHARGE_STATUS_SUCCESS)) {
			callBackOrderState = CallBackOrderState.SUCCESS;
			// 成功通知风控系统
			boolean flag = lockRedisDAO.lockOrder(chargeOrderId + "ZJLS", "success");
			logger.info("flag:" + flag);
			if (flag) {
				ChargeRequest chargeRequest = new ChargeRequest();
				chargeRequest.setPayerUserId(orderRechargeDO.getPayerUserId());
				UserActDO payerUserActDO = getPayerActInfo(chargeRequest);


				this.newupdateRisk(TradeType.BALANCE_RECHARGE, orderRechargeDO.getOrderId(), orderRechargeDO.getPlatChannelId(), orderRechargeDO.getBusinessType(), null,
						orderRechargeDO.getPayerUserId(), null, orderRechargeDO.getPayAmount().intValue(), String.valueOf(orderRechargeDO.getRechargeChannel()), orderRechargeDO.getSourceIp(), null,
						false, orderRechargeDO.getAddTime());
				TradeFlowMessage message = new TradeFlowMessage();
				
				message.setTradeType(TradeMessageType.CHARGE.getCode());
				message.setBerbonAcc(orderRechargeDO.getPayerUserId());
				message.setBusinessType(orderRechargeDO.getBusinessType());
				message.setTradeAmount(orderRechargeDO.getRechargeAmount());
				message.setReceiveAmount(orderRechargeDO.getPayAmount());
				message.setOtherBerbonAcc(null);
				message.setPayOrderNo(chargeOrderId);
				message.setTradeOrderNo(orderRechargeDO.getOrderId());
				message.setFee(orderRechargeDO.getRechargeFee());
				
				
				
				message.setPayType(getpayTypeByBankId(orderRechargeDO.getPayBankId(), orderRechargeDO.getPayerUserId(), orderRechargeDO.getPayerBindNo()));
				
				sendTradeFlowMessage(message);

			}
		} else if (transferOrderState.equals(ChargeOrderState.CHARGE_STATUS_FAIL)) {
			callBackOrderState = CallBackOrderState.FAIL;
		} else if (transferOrderState.equals(ChargeOrderState.CHARGE_STATUS_EXCEPTION)) {
			callBackOrderState = CallBackOrderState.EXCEPTION;
		} else {
			return;
		}
		if (callBackOrderState != null) {
			CallBackInfo callBackInfo = new CallBackInfo();
			callBackInfo.setTradeOrderId(chargeOrderId);
			callBackInfo.setOutOrderId(orderRechargeDO.getOrderId());
			callBackInfo.setNotfiyUrl(orderRechargeDO.getNotifyUrl());
			callBackInfo.setReturnUrl(orderRechargeDO.getReturnUrl());
			callBackInfo.setTotalFee(orderRechargeDO.getRechargeFee().intValue());
			callBackInfo.setPayAmount(orderRechargeDO.getPayAmount().intValue());
			callBackInfo.setAttach(orderRechargeDO.getRemark());
			callBackInfo.setPayTime(payTime);
			callBackInfo.setTradeCrateTime(orderRechargeDO.getAddTime());
			callBackInfo.setOrderType(TradeOrderType.CHARGE_ORDER);
			callBackInfo.setOrderState(callBackOrderState);
			callBackService.callBack(callBackInfo);
		}
	}

	private String recordCardInfo(ChargeRequest chargeRequest) {
		String userId = chargeRequest.getPayerUserId();
		String bankId = chargeRequest.getBankId();

		Integer bindType = chargeRequest.getBindType();
		Integer cardActType = chargeRequest.getCardActType();
		Integer cardType = chargeRequest.getCardType();
		String realName = chargeRequest.getRealName();
		String identityNo = chargeRequest.getIdentityNo();
		String mobileNo = chargeRequest.getMobileNo();
		String cardNo = chargeRequest.getCardNo();
		Boolean bindCardFlag = chargeRequest.getBindCardFlag();
		String cvv = chargeRequest.getCvv();
		String expireDate = chargeRequest.getExpireDate();
		expireDate = com.sztx.pay.center.common.util.DateUtil.tranExpireDate(expireDate);
		String cardProvince = chargeRequest.getCardProvince();
		String cardCity = chargeRequest.getCardCity();
		String bankAddr = chargeRequest.getBankAddr();

		if (StringUtil.isNotBlank(bankId) && bindCardFlag != null && bindCardFlag) {
			List<UserBindCardDO> bindCardDOs = userBindCardMysqlDAO.findByCardNo(userId, BindCardType.BIND_QUICK_PAY.getValue(), cardNo);

			if (!CollectionUtils.isEmpty(bindCardDOs)) {
				// 绑卡状态，0未认证，1已认证, 2已解绑
				for (UserBindCardDO userBindCardDO : bindCardDOs) {
					int status = userBindCardDO.getStatus();
					if (status == 1) {
						throw new BusinessException("该用户已经绑定了该银行卡,不能重复绑定");
					}
				}
			}

			// 查询银行信息
			BankCardInfo bankCardInfo = getBankCardInfo(cardNo);
			String bankName = bankCardInfo.getBankName();
			String bankType = bankCardInfo.getBankType();
			String swiftCode = bankCardInfo.getSwiftCode();

			String bindCardNo = billnoService.nexBindCardNo();
			Date mDate = new Date();

			UserBindCardDO bindCardDO = new UserBindCardDO();
			bindCardDO.setBankName(bankName);
			bindCardDO.setBankType(bankType);
			bindCardDO.setBindCardNo(bindCardNo);
			bindCardDO.setCardActType(cardActType);
			bindCardDO.setCardCity(cardCity);
			bindCardDO.setCardNo(YHBFSensitiveEnc.sensitiveEnc(cardNo, "cardno"));
			bindCardDO.setCardProvince(cardProvince);
			bindCardDO.setCardCity(cardCity);
			bindCardDO.setCreateTime(mDate);
			bindCardDO.setCardCvv(cvv);
			bindCardDO.setBankAddr(bankAddr);
			bindCardDO.setExpireDate(expireDate);
			bindCardDO.setIdentityNo(YHBFSensitiveEnc.sensitiveEnc(identityNo, "identityno"));
			bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
			bindCardDO.setIsMainCard(0);
			bindCardDO.setMobileNo(YHBFSensitiveEnc.sensitiveEnc(mobileNo, "mob"));
			bindCardDO.setModifyTime(mDate);
			bindCardDO.setRealName(realName);
			bindCardDO.setStatus(0); // 未验证
			bindCardDO.setSwiftCode(swiftCode);
			bindCardDO.setUserId(userId);
			bindCardDO.setBindType(BindCardType.BIND_QUICK_PAY.getValue());
			bindCardDO.setCardType(cardType);
			bindCardDO.setBankId(bankId);

			userBindCardMysqlDAO.save(bindCardDO);

			// this.payerBindCardInfo =
			// accountService.findUserBindInfo(bindCardNo, userId,
			// BindCardType.BIND_QUICK_PAY);
			UserBindCardDO cardInfo = userBindCardMysqlDAO.findByBindCardNo(userId, null, bindCardNo);
			bindCardDODec(cardInfo);
			this.payerBindCardInfo = cardInfo;
			return bindCardNo;
		} else {
			return chargeRequest.getBindNo();
		}
	}

	private void bindCardDODec(UserBindCardDO bindCardDO) {
		if (bindCardDO == null) {
			return;
		}
		String cardNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getCardNo(), "cardno");
		// String realName =
		// YHBFSensitiveEnc.sensitiveDec(bindCardDO.getRealName(), "realname");
		String realName = bindCardDO.getRealName();
		String identityNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getIdentityNo(), "identityno");
		String mobileNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getMobileNo(), "mob");
		bindCardDO.setCardNo(cardNo);
		bindCardDO.setRealName(realName);
		bindCardDO.setIdentityNo(identityNo);
		bindCardDO.setMobileNo(mobileNo);
	}

	private BankCardInfo getBankCardInfo(String cardNo) {

		ReqGetBankCardInfo requestBankCardInfo = new ReqGetBankCardInfo();
		cardNo = YHBFSensitiveEnc.passDatasensitiveEnc(cardNo,"cardno");
		requestBankCardInfo.setBankCardNo(cardNo);
		BankUtilRpcService bankUtilRpcService = dubboConsumerFactory.getDubboClient("bankUtilRpcService");

		logger.info("GetBankCardInfo Request:" + JSONObject.toJSONString(requestBankCardInfo));
		RespGetBankCardInfo respBankCardInfo = bankUtilRpcService.getBankCardInfo(requestBankCardInfo);
		if (respBankCardInfo == null) {
			logger.error("get bank card info not response.");
			throw new BusinessException("服务器忙，请稍后再试");
		}
		logger.info("getBankCardInfo Response:" + JSONObject.toJSONString(respBankCardInfo));

		String resultCode = respBankCardInfo.getResultCode();
		String resultMsg = respBankCardInfo.getResultMsg();

		if (!RespBindBankCard.RC_OK.equals(resultCode)) {
			logger.warn("get bank card info error." + resultMsg);
			throw new BusinessException(resultMsg);
		}

		return respBankCardInfo.getCardInfo();
	}
	
	private boolean sendTradeFlowMessage(TradeFlowMessage message) {
		String json = JSONObject.toJSONString(message);
		mqMessageService.sendTradeFlowMsg(json);
		return true;
	}	
	
	private String getpayTypeByBankId(String bankId, String payerUserId, String bindNo){
		if (!StringUtils.isBlank(bankId)) {
			if(bankId.startsWith("0"))
				return "倍棒余额";
			else if(bankId.startsWith("1"))
				return "网银支付";
			else if(bankId.startsWith("2")){
				UserBindCardDO userBindCardDO = accountService.findUserBindInfoIgnoreState(bindNo, payerUserId, BindCardType.BIND_QUICK_PAY);
				String cardNo = YHBFSensitiveEnc.sensitiveDec(userBindCardDO.getCardNo(), "cardno");
				cardNo = cardNo.substring(cardNo.length() - 4, cardNo.length());
				String payType = userBindCardDO.getBankName() + "(" + cardNo + ")";
				return payType;
			}else if(bankId.startsWith("3")){
				if(("3000000").equals(bankId))
					return "支付宝WAP支付";
				else if(("3000001").equals(bankId))
					return "微信公众号支付";
				else if(("3000002").equals(bankId))
					return "微信APP支付";
				else  if(("3000003").equals(bankId))
					return "微信APP支付";
				else  if(("3000004").equals(bankId))
					return "威富通支付宝扫码支付";
				else  if(("3000005").equals(bankId))
					return "威富通微信扫码支付";
			}
			return null;
		} else {
			UserBindCardDO userBindCardDO = accountService.findUserBindInfo(bindNo, payerUserId, BindCardType.BIND_QUICK_PAY);
			String cardNo = YHBFSensitiveEnc.sensitiveDec(userBindCardDO.getCardNo(), "cardno");
			cardNo = cardNo.substring(cardNo.length() - 4, cardNo.length());
			String payType = userBindCardDO.getBankName() + "(" + cardNo + ")";
			return payType;
		}
	}

}
